<?php
Yii::import('application.components.auction.dataSource.*');
Yii::import('application.components.auction.behavior.*');
/**
 * 
 * @author Administrator
 * @method public create
 * @method public live
 * @method public end
 * 
*/
class AuData extends CFormModel{
	
	public $id;
	public $title;
	public $short_description;
	public $description;
		
	public $price_value;
	public $price_vendor;
	public $price_shipping;
	public $price_billing;
	public $price_current;
	public $status;
	public $meta_title;
	public $meta_keyword;
	public $meta_description;
	public $friendly_url;
	public $winner_name;
	public $winner_id;
	
	public $start_time;
	public $end_time;
	
	public $scene;
	
	private $_meta;
	
	public function __construct($scene = null){
		$this->scene = $scene;
		parent::__construct($scene);
	}
	
	public function className(){
		return get_class($this);
	}
	
	public function primary(){
		return $this->id;
	}
	
	public function meta(){
		if (!$this->_meta instanceof AuDataMate) {
			$this->_meta  = new AuDataMate($this);
			$this->_meta->buildDataSource();
			$this->_meta->buildBehavior();
		}
		return $this->_meta;
	}
	
	public function dataSource(){
		return array(
			array(array('id','title'),'AuDb'),
			array(array('short_description'),'AuCache'),
		);
	}
	
	public function dataSourceRelations(){
		return array(
			'AuDb' => array(
				array('AuCache')
			)
		);
	}
	
	public function auctionBehavior(){
		return array(
			array('create','AuBeCreate'),
		);
	}
	
	
	
	/*
	public function find($aushelf = null){
		foreach ($this->meta()->dataSourceList() as $dataSource){
			$dataSource->find($aushelf);
		}
		return $this;
	}*/
	
	/*
	public function findAll($aushelf = null){
		$findAll = array();
		foreach ($this->meta()->dataSourceList() as $dataSource){
			$findAllSet = $dataSource->findAll($aushelf);
			if (!empty($findAllSet)) {
				foreach ($findAllSet as $findAllSetData){
					if (!array_key_exists($findAllSetData->primary(),$findAll)){
						$findAll[$findAllSetData->primary()] = $findAllSetData;
					}
					$findAll[$findAllSetData->primary()]->attributes($dataSource->buildMapperValue($findAllSetData->getAttributes()));
				}	
			}
		}
		return $findAll;
	}
	*/
	public function find($aushelf = null){
		foreach ($this->meta()->dataSourceRelationList() as $dataSource){
			$dataSource->find($aushelf);
			if (!empty($dataSource->result)){
				foreach ($dataSource->getRelation() as $relation){
					$relationAushelf = new AuShelf();
					$relationAushelf->primary = $this->primary();
					$relation->find($relationAushelf);
				}
			}
		}
		return $dataSource->result;
	}
	public function findAll($aushelf = null){
		$findAll = null;
		foreach ($this->meta()->dataSourceRelationList() as $dataSource){
			$dataSource->findAll($aushelf);
			if (!empty($dataSource->result)){
				foreach ($dataSource->result as $dataSourceRow){
					foreach ($dataSourceRow->meta()->getDataSource($dataSource->sourceName())->getRelation() as $relation){
						$relationAushelf = new AuShelf();
						$relationAushelf->primary = $dataSourceRow->primary();
						$relation->find($relationAushelf);
					}
					$findAll[] = $dataSourceRow;
				}
			}
		}
		$dataSource->result = $findAll;
		return $dataSource->result;
	}
	
	public function attributes($attributes){
		foreach ($attributes as $key => $value){
			if (property_exists($this,$key)){
				$this->$key = $value;
			}
		}
		return $this;
	}
	
	public function toArray(){
		return json_decode(json_encode($this),true);
	}
	
	public function __call($callName,$arguments){
		if ($this->meta()->hasBehavior($callName)) {
			return $this->meta()->getBehavior($callName)->run();
		}
		if (method_exists($this->meta(),$callName)){
			return call_user_func_array(array($this->meta(),$callName),$arguments);
		}
		//throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',array('{class}'=>get_class($this), '{property}'=>$name)));
	}
	
	
}
class AuDataMate extends AuPrototype{
	protected $_dataSource = array();
	protected $_dataSourceRelations = array();
	protected $_behavior = array();
	
	public function addDataSource($dataSourceConfig){
		
		if (!array_key_exists('scene',$dataSourceConfig) || $dataSourceConfig['scene'] == $this->getPrototype()->scene) {
			if (!$this->hasDataSource($dataSourceConfig[1])) {
				$this->setDataSource($dataSourceConfig[1],new $dataSourceConfig[1]($this->getPrototype()));
			}
			$this->getDataSource($dataSourceConfig[1])->addMapper($dataSourceConfig[0]);
		}
		
		return $this;
	}
	
	public function buildDataSource(){
		foreach ($this->getPrototype()->dataSource() as $sourceConfig){
			$this->addDataSource($sourceConfig);
		}

		foreach ($this->getPrototype()->dataSourceRelations() as $dataRelations => $dataRelationSources){
			foreach ($dataRelationSources as $relationSource){
				$this->_dataSourceRelations[$dataRelations] = $this->getDataSource($dataRelations)->addRelation($this->getDataSource($relationSource[0]));
			}
		}
	}
	
	public function hasDataSource($dataSourceName){
		return array_key_exists($dataSourceName,$this->_dataSource);
	}
	
	public function getDataSource($dataSourceName){
		return $this->_dataSource[$dataSourceName];
	}
	
	
	public function setDataSource($dataSourceName,$dataSourceClass){
		$this->_dataSource[$dataSourceName] = $dataSourceClass;
		return $this;
	}
	
	
	public function dataSourceList(){
		return $this->_dataSource;
	}
	
	public function dataSourceRelationList(){
		return $this->_dataSourceRelations;
	}
	
	public function addBehavior($behaviorConfig){
		
		if (!array_key_exists('scene',$behaviorConfig) || $behaviorConfig['scene'] == $this->getPrototype()->scene) {
			$this->setBehavior($behaviorConfig[0],new $behaviorConfig[1]($this->getPrototype()));
		}
		
		return $this;
	}
	
	public function buildBehavior(){
		foreach ($this->getPrototype()->auctionBehavior() as $behaviorConfig){
			$this->addBehavior($behaviorConfig);
		}
		return $this;
	}
	
	public function hasBehavior($behaviorName){
		return array_key_exists($behaviorName,$this->_behavior);
	}
	
	public function getBehavior($behaviorName){
		return $this->_behavior[$behaviorName];
	}
	
	public function setBehavior($behaviorName,$behaviorClass){
		$this->_behavior[$behaviorName] = $behaviorClass;
		return $this;
	}
	
}